import winrm
import json
from exchange.logger import log
from exchange.common.const import CmdRetCode, ExchangeResourceKeyName, ErrorCode
from exchange.common.exchange_exception import ErrCodeException
from exchange.common.exchange_common import get_env_variable, parse_sql_result, check_special_characters

class ExchangeClient(object):
    def __init__(self, pid: str, param):
        """
        初始化 Exchange 客户端，使用 winrm 连接到 Exchange 服务器。
        :param pid: 请求 ID
        :param param: 请求参数，包含 Exchange 服务器的连接信息
        """
        self.pid = pid
        self.param = param
        self.username = ''
        self.password = ''
        self.session = None
        if self.param.get('application', ''):
            self.app_info = self.param.get('application')
        else:
            self.app_info = self.param.get("applications", {})[0]
        self.group_name = self.app_info.get("name", "")
        self.app_extend_info = self.app_info.get('extendInfo', '')
        self.exchange_host = self.app_extend_info.get("exchange_host", "")
        self.port = self.app_extend_info.get("port", 5985)  # 默认的 winrm 端口

        self._connect_to_exchange_server()

    def get_auth_from_param(self):
        log.info("deal with auth")
        username = get_env_variable(f'{ExchangeResourceKeyName.APPENV_AUTH_AUTHKEY}{self.pid}')
        password = get_env_variable(f'{ExchangeResourceKeyName.APPENV_AUTH_AUTHPWD}{self.pid}')
        if not username or not password:
            username = get_env_variable(f'{ExchangeResourceKeyName.LIST_APPLICATION_AUTH_AUTHKEY}{self.pid}')
            password = get_env_variable(f'{ExchangeResourceKeyName.LIST_APPLICATION_AUTH_AUTHPWD}{self.pid}')

        if not username or not password:
            username = get_env_variable(f'{ExchangeResourceKeyName.APPLICATION_AUTH_AUTHKEY}{self.pid}')
            password = get_env_variable(f'{ExchangeResourceKeyName.APPLICATION_AUTH_AUTHPWD}{self.pid}')

        if not username or not password:
            username = get_env_variable(f'{ExchangeResourceKeyName.JOB_TARGETENV_AUTH_AUTHKEY}{self.pid}')
            password = get_env_variable(f'{ExchangeResourceKeyName.JOB_TARGETENV_AUTH_AUTHPWD}{self.pid}')

        self.username, self.password = username, password

    def _connect_to_exchange_server(self):
        """
        使用 winrm 连接到 Exchange 服务器，并创建会话。
        """
        self.get_exchange_version()
        try:
            self.session = winrm.Session(self.exchange_host, auth=(self.username, self.password), transport='ntlm', port=self.port)
            log.info(f"Successfully connected to Exchange server {self.exchange_host}")
        except Exception as e:
            log.error(f"Failed to connect to Exchange server {self.exchange_host}. Error: {e}")
            raise ErrCodeException(ErrorCode.ERR_CONNECTION,
                                   f"Failed to connect to Exchange server {self.exchange_host}", str(e))

    def execute_ps_command(self, command: str):
        """
        执行 PowerShell 命令并返回输出结果。
        :param command: 要执行的 PowerShell 命令。
        :return: 命令执行的标准输出和错误信息。
        """
        try:
            # 执行命令并捕获标准输出和标准错误
            result = self.session.run_ps(command)
            std_out = result.std_out.decode().strip()
            std_err = result.std_err.decode().strip()

            if result.status_code != 0:
                log.error(f"PowerShell command failed. StdErr: {std_err}")
                raise ErrCodeException(ErrorCode.ERR_COMMAND_EXECUTION,
                                       f"PowerShell command execution failed: {std_err}", std_err)

            log.info(f"PowerShell command executed successfully. StdOut: {std_out}")
            return std_out, std_err
        except Exception as e:
            log.error(f"Failed to execute PowerShell command. Error: {e}")
            raise ErrCodeException(ErrorCode.ERR_COMMAND_EXECUTION, "Failed to execute PowerShell command", str(e))

    def check_exchange_connectivity(self):
        """
        检查 Exchange 服务器的连通性，通过执行简单的 PowerShell 命令确认是否可以连接。
        :return: 如果连接成功返回 True，否则抛出异常。
        """
        command = "Get-Service MSExchangeIS"
        std_out, std_err = self.execute_ps_command(command)

        if "running" in std_out.lower():
            log.info("Exchange server is up and running.")
            return True
        else:
            log.error("Exchange server is not running.")
            raise ErrCodeException(ErrorCode.ERR_SERVER_NOT_RUNNING, "Exchange server is not running", std_err)

    def get_exchange_version(self):
        """
        获取 Exchange 服务器的版本信息。
        :return: Exchange 服务器的版本号。
        """
        command = "Get-ExchangeServer | Select-Object Name, AdminDisplayVersion"
        std_out, std_err = self.execute_ps_command(command)

        if std_out:
            version_info = std_out.split('\n')[1].strip()
            version = version_info.split()[-1]  # 获取最后一部分，即版本号
            log.info(f"Exchange server version: {version}")
            return version
        else:
            log.error("Failed to retrieve Exchange server version.")
            raise ErrCodeException(ErrorCode.ERR_VERSION_RETRIEVAL, "Failed to retrieve Exchange server version",
                                   std_err)

    def get_exchange_server_name(self):
        """
        获取 Exchange 服务器的名称。
        :return: 返回服务器的名称。
        """
        command = "Get-ExchangeServer | Select-Object Name"
        std_out, std_err = self.execute_ps_command(command)

        if std_out:
            server_name = std_out.split('\n')[1].strip()
            log.info(f"Exchange server name: {server_name}")
            return server_name
        else:
            log.error("Failed to retrieve Exchange server name.")
            raise ErrCodeException(ErrorCode.ERR_SERVER_NAME_RETRIEVAL, "Failed to retrieve Exchange server name", std_err)

    def get_exchange_server_role(self):
        """
        获取 Exchange 服务器的角色（如：Mailbox, CAS, Hub）。
        :return: 返回服务器的角色。
        """
        command = "Get-ExchangeServer | Select-Object Name, ServerRole"
        std_out, std_err = self.execute_ps_command(command)

        if std_out:
            role_info = std_out.split('\n')[1].strip()
            roles = role_info.split()[-1]  # 获取最后一部分，即角色
            log.info(f"Exchange server role: {roles}")
            return roles
        else:
            log.error("Failed to retrieve Exchange server role.")
            raise ErrCodeException(ErrorCode.ERR_SERVER_ROLE_RETRIEVAL, "Failed to retrieve Exchange server role", std_err)

    def get_exchange_server_config(self):
        """
        获取 Exchange 服务器的配置信息（如：最大邮件大小等）。
        :return: 返回服务器的配置信息。
        """
        command = "Get-ExchangeServer | Select-Object Name, *"
        std_out, std_err = self.execute_ps_command(command)

        if std_out:
            config_info = std_out.strip().split("\n")
            log.info(f"Exchange server configuration: {config_info}")
            return config_info
        else:
            log.error("Failed to retrieve Exchange server configuration.")
            raise ErrCodeException(ErrorCode.ERR_SERVER_CONFIG_RETRIEVAL, "Failed to retrieve Exchange server configuration", std_err)